package foodmaterial.service.impl;

import foodmaterial.dao.DocumentTrackDao;
import foodmaterial.dao.FoodMaterialDao;
import foodmaterial.dao.InitDao;
import foodmaterial.dao.PurchaseDao;
import foodmaterial.dto.PurchaseBillDto;
import foodmaterial.dto.PurchasePlanDto;
import foodmaterial.dto.PurchaseSummaryDto;
import foodmaterial.dto.SupplierDto;
import foodmaterial.entity.*;
import foodmaterial.service.PurchaseService;
import foodmaterial.utils.Arithmetic;
import foodmaterial.utils.Constants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.*;

@Service
public class PurchaseServiceImpl extends BaseService implements PurchaseService {
    @Autowired
    private PurchaseDao dao ;

    @Autowired
    private InitDao initDao ;

    @Autowired
    private FoodMaterialDao foodMaterialDao ;

    @Autowired
    private DocumentTrackDao documentTrackDao ;

    @Override
    public int addSupplier(Supplier supplier) {
        supplier.setId(nextId());
        return dao.insertSupplier(supplier);
    }

    @Override
    public int modifySupplier(Supplier supplier) {
        return dao.updateSupplier(supplier);
    }

    @Override
    public Supplier querySupplierById(SupplierDto dto) {
        List<Supplier> list = dao.selectSupplier(dto) ;
        return list.isEmpty() ? null : list.get(0);
    }

    @Override
    public List<Supplier> querySuppliers(SupplierDto dto) {
        List<Supplier> result = dao.selectSupplier(dto) ;
        String imageServerAddress =
                initDao.selectSysParamsByCode(Constants.IMAGE_SERVER_ADDRESS).getParamValue();
        for (Supplier supplier1 : result) {
            if (StringUtils.isEmpty(supplier1.getCredentials()) == false) {
                supplier1.setHasCredentials(true);
            }
        }
        return result ;
    }

    /**
     * 更新库存和进货价格
     * @param purchaseBill
     * @return
     */
    private int modifyFoodMaterial(PurchaseBill purchaseBill,List<FoodMaterial> oldStock) {
        List<PurchaseBillDetails> list = purchaseBill.getDetails() ;
        int rows = 0 ;
        List<FoodMaterial> lock = null;
        Collections.sort(list);
        lock = foodMaterialDao.selectFoodMaterialByIds(list);
        for (int i = 0; i < lock.size(); i++) {
            FoodMaterial fm = lock.get(i);
            fm.setAmount(new BigDecimal(list.get(i).getAmount()));
            if (Constants.PURCHASE_BILL_TYPE_BATCH.equals(purchaseBill.getBillType()) &&
                    (fm.getLastBuyDate() == null || fm.getLastBuyDate().getTime() <= purchaseBill.getPurchaseDate().getTime())) {
                fm.setLastBuyDate(purchaseBill.getPurchaseDate());
                fm.setEnableUpdateBuyPrice(true);
                fm.setBuyPrice(list.get(i).getPrice());
            }
        }
        rows = foodMaterialDao.updateFoodMaterialBuyPriceAndStock(lock);
        if (oldStock != null && oldStock.isEmpty() == false)
            foodMaterialDao.updateFoodMaterialStock(oldStock) ;//减库存
        return rows ;
    }

    private BigDecimal setDetails(PurchaseBill purchaseBill) {
        BigDecimal total = new BigDecimal("0.00");
        List<PurchaseBillDetails> list = purchaseBill.getDetails() ;
        for (PurchaseBillDetails p : list) {
            p.setId(nextId());
            p.setPurchaseBillId(purchaseBill.getId());
            p.setTotal(Arithmetic.mul(p.getPrice(),new BigDecimal(p.getAmount()),2));
            total = Arithmetic.add(p.getTotal(),total,2) ;
        }
        return total ;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int addPurchaseBill(PurchaseBill purchaseBill) {
        purchaseBill.setId(nextId());
        purchaseBill.setOperationPerson(this.getSysUser().getId());
        purchaseBill.setStatus(false);
        purchaseBill.setOperationDate(new Date());
        List<PurchaseBillDetails> list = purchaseBill.getDetails() ;
        BigDecimal total = setDetails(purchaseBill);
        purchaseBill.setAmountOfMoney(total);
        dao.insertPurchaseBill(purchaseBill) ;
        dao.insertPurchaseBillDetails(purchaseBill.getDetails()) ;
        return modifyFoodMaterial(purchaseBill,null) ;
    }

    private PurchaseBillDetails getPurchaseBillDetail(List<PurchaseBillDetails> details,Long id) {
        for (PurchaseBillDetails detail : details) {
            if (detail.getFoodMaterialId().longValue() == id.longValue()) return detail ;
        }
        return null ;
    }

    private void compareDetail(PurchaseBillDetails newDetail,PurchaseBillDetails oldDetail,StringBuilder sb) {
        if (newDetail.getAmount().intValue() != oldDetail.getAmount().intValue()) {
            sb.append("修改了食材[").append(oldDetail.getFoodMaterialName())
                    .append("]的数量，改前：")
                    .append(oldDetail.getAmount())
                    .append("，改后：").append(newDetail.getAmount()).append("；");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int modifyPurchaseBill(PurchaseBill purchaseBill) {
        purchaseBill.setOperationDate(new Date());
        SysUser userDetails = this.getSysUser();
        if (purchaseBill.getUpdateSelf() == false) {//修改别人的采购单
            if (purchaseBill.getOperationPerson() != userDetails.getId()) {
                purchaseBill.setLastUpdatePerson(userDetails.getId());
                purchaseBill.setLastUpdateTime(new Date());
            }
        }
        List<PurchaseBillDetails> list = purchaseBill.getDetails() ;

        List<FoodMaterial> list1 = new ArrayList<>() ;
        List<PurchaseBillDetails> oldList = dao.selectPurchaseBillDetails(purchaseBill.getId()) ;
        Map<Long,FoodMaterial> map = new HashMap<>() ;
        for (PurchaseBillDetails p : oldList) {
            FoodMaterial fm = new FoodMaterial() ;
            fm.setId(p.getFoodMaterialId());
            fm.setAmount(new BigDecimal(-p.getAmount()));
            map.put(fm.getId(),fm) ;
        }
        list1.addAll(map.values()) ;
        BigDecimal total = this.setDetails(purchaseBill);
        purchaseBill.setAmountOfMoney(total);
        dao.deletePurchaseBillDetails(purchaseBill.getId()) ;
        dao.updatePurchaseBill(purchaseBill) ;
        dao.insertPurchaseBillDetails(list) ;

        StringBuilder sb = new StringBuilder() ;
        for (PurchaseBillDetails oldDetail : oldList) {
            PurchaseBillDetails findDetail = this.getPurchaseBillDetail(list,oldDetail.getFoodMaterialId()) ;
            if (findDetail != null) compareDetail(findDetail,oldDetail,sb) ;
            else { //老明细中存在的食材在新明细中不存在
                sb.append("删除了食材[").append(oldDetail.getFoodMaterialName())
                        .append("]，数量是：").append(oldDetail.getAmount())
                        .append("]；");
            }
        }

        for (PurchaseBillDetails newDetail : list) {
            PurchaseBillDetails findDetail = this.getPurchaseBillDetail(oldList,newDetail.getFoodMaterialId()) ;
            if (findDetail == null) { //老明细中不存在的食材在新明细中存在
                sb.append("添加了食材[").append(newDetail.getFoodMaterialName())
                        .append("]，数量是：").append(newDetail.getAmount()).append("；");
            }
        }

        if (sb.length() > 0) {
            DocumentTrack track = this.getDocumentTrack(purchaseBill.getId(),1,sb) ;
            documentTrackDao.insertDocumentTrack(track) ;
        }

        return modifyFoodMaterial(purchaseBill,list1) ;
    }

    @Override
    public List<PurchaseBill> queryPurchaseBill(PurchaseBillDto dto) {
        if (dto.getUpdateSelf() != null && dto.getUpdateSelf()) {
            dto.setOperationPerson(this.getSysUser().getId());
        }
        return dao.selectPurchaseBill(dto);
    }

    @Override
    public List<PurchaseBillDetails> queryPurchaseBillDetails(Long purchaseBillId) {
        List<PurchaseBillDetails> list = dao.selectPurchaseBillDetails(purchaseBillId);
        return list ;
    }

    @Override
    public PurchaseBill queryPurchaseBillById(Long id) {
        return dao.selectPurchaseBillById(id);
    }

    @Override
    public List<PurchaseBill> queryPrintPurchaseBill(List<Long> ids) {
        return dao.selectPrintPurchaseBill(ids);
    }

    @Override
    public List<PurchaseBillDetails> queryPlan(PurchasePlanDto dto) {
        return dto.getOriginalProcess().booleanValue() == false ?
                dao.selectPlan(dto): dao.selectProcessPlan(dto);
    }

    @Override
    public List<PurchaseBillDetails> queryPurchaseSummary(PurchaseSummaryDto dto) {
        return dao.selectPurchaseSummary(dto);
    }

    @Override
    public Double queryPurchaseSummaryTotalMoney(PurchaseSummaryDto dto) {
        return dao.selectPurchaseSummaryTotalMoney(dto);
    }

    @Override
    public String truncateSupplier() {
        if (dao.checkSupplier() > 0) return "供应商信息已经被使用了，不能清理";
        dao.truncateSupplier();
        return null;
    }
}
